package clientservice;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

/**
 *
 * @author ZeM
 */
public class service {

    Socket socket;
    DataOutputStream dos;
    DataInputStream dis;

    /**
     * Connection to client
     * @param host client IP adress
     * @param port client port
     * @return true if successfully connected
     */
    public boolean Connect(String host, int port) {

        try {

            socket = new Socket();
           
            socket.setSoTimeout(5000); //setting socket timeout
            socket.connect(new InetSocketAddress(host, port)); //connecting to host:port
            if (socket.isConnected()) { //if succesfully connected
                CreateOutputStream(); //Create output stream
                CreateInputStream();  //Create input stream
            }

        } catch (Exception error) {
            return false;
        }

        return true;
    }

    /**
     * Login of server user in client
     * @param user_name
     * @param key key byte code;
     * @return true if login successfull
     */
    public boolean LogIn(String user_name, byte[] key) {
        //Log client into system
        //if successfull return 'true'
        try {
            SendMessageUTF(user_name);
            if (dis.readBoolean() == true) {
                //such user exists in user list on client side
                //get public key
                String publickey = getUTF();
                //get modulus
                String modulus = getUTF();
                //encrypt key
              
                //send encrypted message
              
                if (dis.readBoolean() == true) {
                    //keys are equal. access granted
                    return true;
                } else {
                    //keys are different
                    return false;
                }
            } else {
                //access deny
                return false;
            }
        } catch (Exception er) {
            return false;
        }

    }

    /**
     * Close connection between client and server
     */
    public void CloseConnection() {
        try {
            dos.close();
            dis.close();
            socket.close();

        } catch (Exception error) {
        }
    }

    /**
     * Sending byte message to client
     * @param message byte that need to send
     * @return true if delivered successfully
     */
    public boolean SendMessageByte(byte message) {
        //sending message to client
        //return true if delivered
        try {
            dos.write(message);
            dos.flush();
            if (dis.readBoolean()) {
                return true;
            } else {
                return false;
            }
        } catch (Exception error) {
            return false;
        }

    }

    /**
     * Sending byte message to client
     * @param message array of bytes that need to send
     * @return true if delivered successfully
     */
    public boolean SendMessageBytes(byte[] message) {
        //sending message to client
        //return true if delivered
        try {
            dos.writeInt(message.length);
            dos.flush();
            if (dis.readBoolean()) {
                dos.write(message, 0, message.length);
                dos.flush();
                if (dis.readBoolean()) {
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } catch (Exception error) {
            return false;
        }

    }

    /**
     * Sending string message to client
     * @param message string that need to send
     * @return true if delivered successfully
     */
    public boolean SendMessageUTF(String message) {
        //sending message to client
        //return true if delivered
        try {
            dos.writeUTF(message);
            dos.flush();
            if (dis.readBoolean()) {
                return true;
            } else {
                return false;
            }
        } catch (Exception error) {
            return false;
        }

    }

    public String getUTF() {
        try {
            String message = dis.readUTF();
            dos.writeBoolean(true);
            dos.flush();
            return message;
        } catch (IOException ex) {
            return null;
        }
    }

    public byte[] getBytes() {
        try {
            int length = dis.readInt();
            byte[] message = new byte[length];
            dos.writeBoolean(true);
            dos.flush();
            dis.read(message, 0, length);
            dos.writeBoolean(true);
            dos.flush();
            return message;
        } catch (IOException ex) {
            return null;
        }
    }

    public byte getByte() {
        try {
            byte message;
            message = dis.readByte();
            dos.writeBoolean(true);
            dos.flush();
            return message;
        } catch (IOException ex) {
            return -128;
        }
    }

    /**
     * Creating output stream
     * @return true if successfully created
     */
    private boolean CreateOutputStream() {
        try {
            dos = new DataOutputStream(socket.getOutputStream());
            return true;
        } catch (Exception error) {
            try {
                dos = new DataOutputStream(socket.getOutputStream());
                return true;
            } catch (Exception error1) {
                return false;
            }
        }
    }

    /**
     * Creating input stream
     * @return true if successfully created
     */
    private boolean CreateInputStream() {
        try {
            dis = new DataInputStream(socket.getInputStream());
            return true;
        } catch (Exception error) {
            try {
                dis = new DataInputStream(socket.getInputStream());
                return true;
            } catch (Exception error1) {
                return false;
            }
        }
    }

    /**
     * Closind Output and input streams
     * @return true if successfully closed
     */
    public boolean CloseIO() {
        try {
            dis.close();
            dos.close();
            return true;
        } catch (Exception error) {
            return false;
        }
    }
}

